package controllers;

import play.*;
import play.data.validation.Required;
import play.db.jpa.GenericModel.JPAQuery;
import play.mvc.*;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

import models.*;

@With(Secure.class)
// this class is used for the login, Doaa El-Hawary
public class Items extends Controller {

	/**
	 * Filling item attributes in createItemView.html rendering the list of all
	 * plans needed to choose one from it in order to be associated with the
	 * item and rendering the result if the method was called after an item has
	 * been created
	 * 
	 * @author Andrew Guirguis
	 * @version 2011.0501
	 * @category C5S3
	 * @params
	 * 
	 *         result: the result displayed when an item is associated with a
	 *         plan *
	 */

	public static void createItemView(String result_item) {
		// new Plan().save(); // just for testing in order to associate the item
		// to a plan
		List<Plan> plans = Plan.findAll();
		if (plans.size() == 0)
			error("No item can be created as there is no plan to associate with it");
		if (result_item != null)
			render(result_item, plans);
		else
			render(plans);
	}

	/**
	 * Creates an item with all its required attributes
	 * 
	 * @author Andrew Guirguis
	 * @version 2011.0425
	 * @category C5S3
	 * @params name: name of the item content: the item content time: time of
	 *         the item date: the date of the item plan: the plan to which the
	 *         item will be associated
	 * @return void
	 * @Modified by: Youssef Selim
	 * @Added assigneeUsername in parameters, to get the username entered to be
	 *        assigned with this item
	 */

	public static void createItem(@Required String name,
			@Required String content, @Required String dateAndTime,
			@Required long planID, String assigneeUsername) {

		Plan plan = Plan.findById(planID);
		System.out.println(planID);
		String username = session.get("username");
		User user = (User) User.find("byUsername", username).fetch().get(0);

		if (!plan.getUsers().contains(user) && !user.isAdmin()) {

			error("You are not autorized to do this action");
		}

		if (validation.hasErrors()) {
			String s = "Oops, Please enter missing details !";

			createItemView(s);
		}
		SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");

		Date date = null;

		try {
			date = formatter.parse(dateAndTime);
		} catch (ParseException e) {
			String s = "Oops, Please enter date correctly dd-MM-yyyy HH:mm:ss !";
			createItemView(s);
		}

		Item item = new Item(name, content, date, plan);
		item.save();

		plan.getItems().add(item);
		plan.save();

		String itemName = item.getName();
		String planName = plan.getName();

		String Result = itemName + " item was associated with " + planName
				+ " plan ";
		assignUsers(assigneeUsername, item.getId(), true, Result);

	}

	/**
	 * Updates/modifies an item then calls editItemView method to be redirected
	 * to editItemView.html with the result and/or the item selected
	 * 
	 * @author Andrew Guirguis
	 * @version 2011.0502
	 * @category C5S4
	 * @params viewItemDetails : true if the form submitted requires viewing
	 *         selected item's details only false if the form submitted requires
	 *         editing an item itemID : the id of the item that will be modified
	 *         or the item which details will be viewed according to
	 *         viewItemDetails name: name of the item content: the item content
	 *         time: time of the item date: the date of the item * @return void
	 * @ModifiedBy: Youssef Selim
	 * @Added assigneeUsername in parameters, to get the username entered to be
	 *        assigned with this item
	 */

	public static void editItem(@Required boolean viewItemDetails,
			@Required Long itemID, @Required String name,
			@Required String content, @Required String dateAndTime,
			String assigneeUsername) {

		Item item = Item.findById(itemID);
		Plan plan = item.getPlan();
		String userName = session.get("username");
		User user = (User) User.find("byUsername", userName).fetch().get(0);

		if (!plan.getUsers().contains(user) && !user.isAdmin()) {

			error("You are not autorized to do this action");
		}

		if (validation.hasErrors() && viewItemDetails) {
			String s = "Oops, Please enter missing details !";

			editItemView(itemID, s, null, null, null, null);
		}

		if (itemID != null && !viewItemDetails) {

			editItemView(itemID, null, null, null, null, null);
		}

		SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");

		Date date = null;

		try {
			date = formatter.parse(dateAndTime);
		} catch (ParseException e) {
			String s = "Oops, Please enter date correctly dd-MM-yyyy HH:mm:ss !";
			editItemView(itemID, s, null, null, null, null);
		}

		item.setName(name);
		item.setContent(content);
		item.setDateAndTime(date);
		item.save();
		String Result = item.getName() + " is edited";
		assignUsers(assigneeUsername, itemID, false, Result);

	}

	/**
	 * modifying item attributes in editingItemView.html rendering the list of
	 * all items needed to choose one from it in order to be modified ,
	 * rendering the result if the method was called after an item has been
	 * edited and rendering the selected item (by default : the first one) in
	 * order to view its details if there is no items in the database the method
	 * returns
	 * 
	 * @author Andrew Guirguis
	 * @version 2011.0501
	 * @param result5
	 * @category C5S4
	 * @params itemID : the id of the item that will be modified or the item
	 *         which details will be viewed
	 * 
	 *         result: the result displayed when an item is associated with a
	 *         plan *
	 */

	public static void editItemView(Long itemID, String result_item,
			String result2, String result3, String result4, String result5) {
		List<Item> items = Item.findAll();
		List<Tag> tags = Tag.findAll();
		List<Eentity> entities = Eentity.findAll();
		List<Topic> topics = Topic.findAll();

		if (itemID != null && itemID > Item.count()) {
			error("Wrong Item ID");
			return;
		}

		if (items.size() == 0) {
			error("No item can be edited as there is no item in the database");
		}
		Item item = (Item) Item.findAll().get(0);
		if (result_item != null || result2 != null || result3 != null
				|| result4 != null || result5 != null) {
			if (itemID != null)
				item = Item.findById(itemID);
			render(item, result_item, result2, result3, result4, result5,
					items, tags, entities, topics);
		} else if (itemID != null) {
			item = Item.findById(itemID);
			render(item, items, tags, entities, topics);
		} else
			render(item, items, tags, entities, topics);

	}

	/**
	 * Adds a Tag to be associated with the item while checking that the item is
	 * already not associated
	 * 
	 * @author Andrew Guirguis
	 * @version 2011.0501
	 * @category C5S5
	 * @params itemID: The id of item to be associated tagID: The id of the tag
	 */

	public static void addTag(Long tagID, Long itemID) {
		Item item = Item.findById(itemID);
		Plan plan = item.getPlan();
		String userName = session.get("username");
		User user = (User) User.find("byUsername", userName).fetch().get(0);

		if (!plan.getUsers().contains(user) && !user.isAdmin()) {

			error("You are not autorized to do this action");
		}

		Tag tag = Tag.findById(tagID);

		String itemName = item.getName();
		String tagName = tag.getName();

		if (tag.getItems().contains(item)) {
			error("The following item " + itemName
					+ " is already associated with the tag " + tagName);
			return;
		}

		tag.getItems().add(item);
		tag.save();
		item.getTags().add(tag);
		item.save();

		editItemView(itemID, null, "The following item " + itemName
				+ " was successfully associated with the tag " + tagName, null,
				null, null);

	}

	/**
	 * Remove a tag from an item while checking that the tag is already not
	 * associated
	 * 
	 * @author Andrew Guirguis
	 * @version 2011.0505
	 * @category C5S5
	 * @params itemID: The id of item to be associated tagID: The id of the tag
	 */

	public static void removeTag(Long tagID, Long itemID) {
		Item item = Item.findById(itemID);
		Plan plan = item.getPlan();
		String userName = session.get("username");
		User user = (User) User.find("byUsername", userName).fetch().get(0);

		if (!plan.getUsers().contains(user) && !user.isAdmin()) {

			error("You are not autorized to do this action");
		}

		Tag tag = Tag.findById(tagID);

		String itemName = item.getName();
		String tagName = tag.getName();

		if (!tag.getItems().contains(item)) {
			error("The following item " + itemName
					+ " is already not associated with the tag " + tagName);
			return;
		}

		tag.getItems().remove(item);
		tag.save();
		item.getTags().remove(tag);
		item.save();

		editItemView(itemID, null, null, null, null, "The following tag "
				+ tagName + " was successfully deassociated from the tag "
				+ itemName);

	}

	/**
	 * Relates an Entity to an item while checking that the item is already not
	 * associated to this Entity
	 * 
	 * @author Andrew Guirguis
	 * @version 2011.0501
	 * @category C5S5
	 * @params itemID: The id of item to be associated entityID: The id of the
	 *         entity
	 */

	public static void relateToEntity(Long entityID, Long itemID) {

		Item item = Item.findById(itemID);
		Plan plan = item.getPlan();
		String userName = session.get("username");
		User user = (User) User.find("byUsername", userName).fetch().get(0);

		if (!plan.getUsers().contains(user) && !user.isAdmin()) {

			error("You are not autorized to do this action");
		}

		Eentity entity = Eentity.findById(entityID);

		String itemName = item.getName();
		String entityName = entity.getName();

		if (entity.getRelatedItems().contains(item)) {
			error("The following item " + itemName
					+ " is already associated with the entity " + entityName);
			return;
		}

		entity.getRelatedItems().add(item);
		entity.save();
		item.setEntity(entity);
		item.save();
		editItemView(itemID, null, null, "The following item " + itemName
				+ " was successfully associated with the Entity " + entityName,
				null, null);
	}

	/**
	 * selecting an entity to relate to an item from the rendered list of
	 * Entities sent to relateToEntityView.html
	 * 
	 * 
	 * @author Andrew Guirguis
	 * @version 2011.0503
	 * @category C5S5
	 * @params result: The result passed from relateToEntity() whether there is
	 *         success in relating a certain item to a certain entity
	 * 
	 */
	public static void relateToTopic(Long topicID, Long itemID) {

		Item item = Item.findById(itemID);
		Plan plan = item.getPlan();
		String userName = session.get("username");
		User user = (User) User.find("byUsername", userName).fetch().get(0);

		if (!plan.getUsers().contains(user) && !user.isAdmin()) {

			error("You are not autorized to do this action");
		}

		Topic topic = Topic.findById(topicID);

		String itemName = item.getName();
		String topicName = topic.getTitle();

		if (topic.getItems().contains(item)) {
			error("The following item " + itemName
					+ " is already associated with the topic " + topicName);
			return;
		}

		topic.getItems().add(item);
		topic.save();
		item.setTopic(topic);
		item.save();

		editItemView(itemID, null, null, null, "The following item " + itemName
				+ " was successfully associated with the topic " + topicName,
				null);
	}

	/**
	 * Assign User/s to an item in the action plan
	 * 
	 * @author Youssef Selim
	 * @version 2011.0503
	 * @category C5S09
	 * @param username
	 *            : the username to assign, itemID: the id of the item the user
	 *            will be assigned to, createEditFlag: a flag to check on which
	 *            view it will redirect whether it's from editItemView or
	 *            createItemView, result: the result string that's rendered
	 *            after submitting
	 */
	public static void assignUsers(String username, long itemID,
			boolean createEditFlag, String result) {

		Item item = Item.findById(itemID);

		if (username.isEmpty())
			result += ". No user assigned to this item";

		if (User.find("byUsername", username).first() == null
				&& !username.isEmpty())
			error("User doesn't exist !");
		if (item == null)
			error("The item doesn't exist !");

		User user = User.find("byUsername", username).first();

		if (item.getUsers().contains(user))
			error("User: " + username + " is already assigned to this item");

		if (!username.isEmpty()) {
			item.getUsers().add(user);
			item.save();
			result += "User: " + username + " has been assigned to this item";
		}

		if (createEditFlag)
			createItemView(result);
		else
			editItemView(itemID, result, null, null, null, null);
	}

}